﻿using System;
using System.Collections.Generic;
using Gonte.Types;

namespace Gonte.Reflection
{
    /// <summary>
    /// Binds the values from the source object to the target one in those properties related by the relationships
    /// </summary>
    public class PropertiesBinder
    {
        #region Constructors

        public PropertiesBinder(Object sourceObject)
        {
            sourceObject_ = sourceObject;
        }

        #endregion

        #region Properties

        public Object SourceObject
        {
            get { return sourceObject_; }
        }

        public List<Tuple<String, String>> PropertyRelationships
        {
            get { return propertyRelationships_; }
        } 

        #endregion

        #region Methods

        public void AddPropertyRelationship(String sourcePropertyName, String targetPropertyName)
        {
            propertyRelationships_.Add(new Tuple<String, String>(sourcePropertyName, targetPropertyName));
        }

        /// <summary>
        /// Transfers all the values mapped by the property relationships from the source object to the target one
        /// </summary>
        /// <param name="targetObject"></param>
        public void Bind(Object targetObject)
        {
            TypeAccessor sourceAccessor = TypeAccessor.GetTypeAccessor(sourceObject_.GetType());

            if (targetObject is DynamicObject)
            {
                DynamicObject dynamicObject = targetObject as DynamicObject;

                foreach (Tuple<String, String> propertyRelationship in propertyRelationships_)
                {
                    Object value = sourceAccessor.GetValue(sourceObject_, propertyRelationship.First);
                    dynamicObject.SetValue(propertyRelationship.Second, value);
                }
            }
            else
            {
                TypeAccessor targetAccessor = TypeAccessor.GetTypeAccessor(targetObject.GetType());

                foreach (Tuple<String, String> propertyRelationship in propertyRelationships_)
                {
                    Object value = sourceAccessor.GetValue(sourceObject_, propertyRelationship.First);
                    targetAccessor.SetValue(targetObject, propertyRelationship.Second, value);
                }
            }
        }

        #endregion

        #region Fields

        private readonly Object sourceObject_;
        // The first string is the source property and the second string is the target property
        private readonly List<Tuple<String, String>> propertyRelationships_ = new List<Tuple<String, String>>();

        #endregion
    }
}
